package com.kakaxi.mybilibili.module.user.model;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.webkit.JavascriptInterface;
import android.webkit.WebView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.kakaxi.mybilibili.common.WebUrlConst;
import com.kakaxi.mybilibili.net.HttpClientHelper;
import com.kakaxi.mybilibili.net.Netroid;
import com.kakaxi.mybilibili.net.StringCacheRequest;
import com.kakaxi.mybilibili.utils.LogUtil;
import com.vincestyling.netroid.Listener;
import com.vincestyling.netroid.NetroidError;

import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.kakaxi.mybilibili.net.HttpClientHelper.quickRequest;

/**
 * 登录数据层实现类
 * Created by kakaxi on 16/12/1.
 */

public class LoginModel implements ILoginModel {

    private Context mContext;
    private WebView mWebView;

    private String mUsername;
    private String mCaptcha;
    private Listener<Map<String, String>> mLoginListener;

    private HttpClient mHttpClient;

    @SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
    @Override
    public void initLogin(Context context, final Listener<String> listener) {
        mContext = context;
        mHttpClient = HttpClientHelper.getInstance();
        // 加载本地网站文件, 为了进行加密而准备的
        mWebView = new WebView(context);
        mWebView.getSettings().setJavaScriptEnabled(true);
        mWebView.addJavascriptInterface(this, "app");
        mWebView.loadUrl("file:///android_asset/index.html");
        // 需要先访问登录网址
        new AsyncTask<String, Void, String>() {

            @Override
            protected String doInBackground(String... params) {
                return HttpClientHelper.quickRequest(mHttpClient, WebUrlConst.LOGIN_URL);
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
                if (s != null) {
                    listener.onSuccess(s);
                } else {
                    listener.onError(new NetroidError("初始化失败!"));
                }
            }
        }.execute();
    }

    @Override
    public void getCaptchaImage(final Listener<Bitmap> listener) {
        new AsyncTask<String, Void, Bitmap>() {
            @Override
            protected Bitmap doInBackground(String... params) {
                return HttpClientHelper.requestToImage(mHttpClient, WebUrlConst
                        .LOGIN_GET_CAPTCHA_URL);
            }

            @Override
            protected void onPostExecute(Bitmap bitmap) {
                super.onPostExecute(bitmap);
                if (bitmap != null) {
                    listener.onSuccess(bitmap);
                } else {
                    listener.onError(new NetroidError("获取验证码失败"));
                }
            }
        }.execute();
    }

    @Override
    public void doLogin(String username, final String password, String captchaStr,
                        Listener<Map<String, String>> listener) {
        mUsername = username;
        mCaptcha = captchaStr;
        mLoginListener = listener;

        new AsyncTask<String, Void, JSONObject>() {
            @Override
            protected JSONObject doInBackground(String... params) {
                String responseStr = quickRequest(mHttpClient, WebUrlConst.LOGIN_GET_KEY_URL);
                LogUtil.d("获取key:" + responseStr);
                return JSON.parseObject(responseStr);
            }

            @Override
            protected void onPostExecute(JSONObject jsonObject) {
                super.onPostExecute(jsonObject);
                if (jsonObject != null) {
                    mWebView.loadUrl("javascript:de('" + jsonObject.getString("key") + "', '" +
                            jsonObject.getString("hash") + password + "')");
                }
            }

        }.execute();
    }

    @Override
    public void getUserInfo(String userId, final Listener<JSONObject> listener) {
        StringCacheRequest request = new StringCacheRequest(WebUrlConst.USER_INFO_URL, "mid=" +
                userId, new Listener<String>() {
            @Override
            public void onSuccess(String response) {
                super.onSuccess(response);
                try {
                    listener.onSuccess(JSON.parseObject(response));
                } catch (Exception ex) {
                    listener.onError(new NetroidError(ex.getMessage()));
                }
            }

            @Override
            public void onError(NetroidError error) {
                super.onError(error);
                listener.onError(error);
            }
        });

        request.addHeader("Referer", "http://space.bilibili.com/" + userId + "/");
        Netroid.addRequest(request, false);
    }

    /**
     * 发送登录
     *
     * @param password 加密后的密码
     */
    @JavascriptInterface
    public void sendLogin(final String password) {
        LogUtil.d("加密后的:" + password);
        new AsyncTask<String, Void, Map<String, Object>>() {
            @Override
            protected Map<String, Object> doInBackground(String... params) {
                // 内容参数
                List<BasicNameValuePair> paramList = new ArrayList<>();
                paramList.add(new BasicNameValuePair("act", "login"));
                paramList.add(new BasicNameValuePair("gourl", ""));
                paramList.add(new BasicNameValuePair("keeptime", "2592000"));
                paramList.add(new BasicNameValuePair("userid", mUsername));
                paramList.add(new BasicNameValuePair("pwd", password));
                paramList.add(new BasicNameValuePair("vdcode", mCaptcha.toUpperCase()));
                // 请求头
                Header[] headers = {
                        new BasicHeader("Host", "passport.bilibili.com"),
                        new BasicHeader("Connection", "keep-alive"),
                        new BasicHeader("Accept", "text/html,application/xhtml+xml," +
                                "application/xml;q=0.9,image/webp,*/*;q=0.8"),
                        new BasicHeader("Upgrade-Insecure-Requests", "1"),
                        new BasicHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X " +
                                "10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661" +
                                ".102 Safari/537.36"),
                        new BasicHeader("Accept-Encoding", "gzip, deflate, sdch"),
                        new BasicHeader("Accept-Language", "zh-CN,zh;q=0.8")
                };
                HttpResponse resultResponse = HttpClientHelper.request(mHttpClient, WebUrlConst
                        .LOGIN_ACTION_URL, paramList, null);
                LogUtil.d("code: " + resultResponse.getStatusLine().getStatusCode());
                for (Header header : resultResponse.getAllHeaders()) {
                    LogUtil.d("name: " + header.getName() + " value: " + header.getValue());
                }
                int code = resultResponse.getStatusLine().getStatusCode();
                Map<String, Object> resultMap = new HashMap<>();
                if (code == HttpStatus.SC_MOVED_TEMPORARILY) { // 重定向
                    Header locationHeader = resultResponse.getFirstHeader("Location");
                    if (locationHeader != null) {
                        resultMap.put("isSuc", "true");
                        resultMap.put("message", "登录成功");
                        resultMap.put("cookie", resultResponse.getHeaders("Set-Cookie"));
                    } else {
                        // 从网页中解析出错误信息
                        String html = HttpClientHelper.getContentString(resultResponse);
                        Document document = Jsoup.parse(html);
                        String failedMessage = document.getElementsByTag("div").first().ownText();
                        resultMap.put("isSuc", "false");
                        resultMap.put("message", failedMessage);
                    }
                } else {
                    resultMap.put("isSuc", "false");
                    resultMap.put("message", "登录出错, 请重试!");
                }
                return resultMap;
            }

            @Override
            protected void onPostExecute(Map<String, Object> responseMap) {
                super.onPostExecute(responseMap);
                String isSuc = (String) responseMap.get("isSuc");
                String message = (String) responseMap.get("message");
                Header[] headers = (Header[]) responseMap.get("cookie");
                if (isSuc != null && isSuc.equals("true") && headers != null) {
                    Map<String, String> cookieMap = new HashMap<>();
                    for (Header header : headers) {
                        // DedeUserID=15175987; Domain=.bilibili.com; Expires=Thu, 05-Jan-2017 14:32:44 GMT; Path=/
                        // 把cookie 拆开
                        String[] cookieInfo = header.getValue().split(";")[0].split("=");
                        cookieMap.put(cookieInfo[0], cookieInfo[1]);
                    }
                    mLoginListener.onSuccess(cookieMap);
                } else {
                    mLoginListener.onError(new NetroidError(message));
                }
            }

        }.execute();
    }

}
